/*
 * Matriz3D.cpp
 *
 *  Created on: 04/10/2009
 *      Author: ale
 */

#include "Matriz3D.h"
#include "Definiciones.h"
#include <cmath>



Matriz3D::Matriz3D() {
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			matriz[i][j] = 0;
}

Matriz3D::Matriz3D(const Matriz3D& otra) {
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			matriz[i][j] = otra.matriz[i][j];
}

Matriz3D::Matriz3D(const float** otra) {
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			matriz[i][j] = otra[i][j];
}

Matriz3D::~Matriz3D() {
}

float* Matriz3D::operator[](int i) {
	return matriz[i];
}

Matriz3D* Matriz3D::operator*(const Matriz3D& otra) {
	Matriz3D* m =  new Matriz3D();
	for(int fila=0;fila<4;fila++) {
		for(int col=0; col<4;col++) {
			float acum=0.0;
			for(int i=0;i<4;i++) {
				acum += (matriz[fila][i] * otra.matriz[i][col]);
			}
			(*m)[fila][col] = acum;
		}
	}

	return m;
}

Punto Matriz3D::operator*(const Punto& punto) {
	float temp[4];
	float temp2[4];
	temp[0] = punto.x();
	temp[1] = punto.y();
	temp[2] = punto.z();
	temp[3] = 1;

	for(int fila=0;fila<4;fila++) {
		float acum=0;
		for(int i=0;i<4;i++) {
			acum += (matriz[fila][i] * temp[i]);
		}
		temp2[fila] = acum;
	}
	return Punto(ROUND_SIGNED(temp2[0]),ROUND_SIGNED(temp2[1]),ROUND_SIGNED(temp2[2]));
}

void Matriz3D::setIdentidad() {
	for (int fila = 0; fila < 4; fila++) {
		for (int col = 0; col < 4; col++) {
			matriz[fila][col] = (fila == col) ? 1 : 0;
		}
	}
}

void Matriz3D::setRotacion(float angulo) {

	float coseno = cos(angulo);
	float seno = sin(angulo);
	this->setIdentidad();
	matriz[0][0] = coseno;
	matriz[1][1] = coseno;
	matriz[0][1] = -seno;
	matriz[1][0] = seno;
}

void Matriz3D::setTraslacion(const Punto& punto){
	this->setIdentidad();
	matriz[0][3] = punto.x();
	matriz[1][3] = punto.y();
	matriz[2][3] = punto.z();
}

void Matriz3D::setEscalado(float factor){
	for (int fila = 0; fila < 4; fila++) {
			for (int col = 0; col < 4; col++) {
				matriz[fila][col] = (fila == col) ? factor : 0;
			}
		}
}

void Matriz3D::setEscalado(const Punto& factores){
	this->setIdentidad();
	matriz[0][0] = factores.x();
	matriz[1][1] = factores.y();
	matriz[2][2] = factores.z();
}

void Matriz3D::setEspejo(){
	setIdentidad();
	matriz[1][1]=-1;
}
